#ifndef _EBN_COMPETENCE_MODULE_H_
#define _EBN_COMPETENCE_MODULE_H_

#include <string>
#include <vector>

#include "EbnCondition.h"
#include "EbnEffect.h"

using namespace std;

class CEbnAction;

class CEbnCompetenceModule
{
public:
    ~CEbnCompetenceModule(void);
    CEbnCompetenceModule(CEbnAction * pAction);

    string getActionName();

    bool hasAction(CEbnAction * pAction);

    CEbnCondition * addCondition(CEbnWorldState * worldState, bool positive = true);
    int getConditionCount(void);
    CEbnCondition * getCondition(int index);
    CEbnCondition * getCondition(string conditionName);

    CEbnEffect * addPostEffect(CEbnWorldState * worldState, bool positive = true);
    int getPostEffectCount(void);
    CEbnEffect * getPostEffect(int index);
    CEbnEffect * getPostEffect(string effectName);

    float getPostEffectExpectation(string effectName);

    bool executeModule();


    void addToLink(CEbnLink * pLink);
    int getToLinkCount(void);
    CEbnLink * getToLink(int index);

    void addFromLink(CEbnLink * pLink);
    int getFromLinkCount(void);
    CEbnLink * getFromLink(int index);

    void resetActivation(void);
    void setActivation(float activation);
    float getActivation(void);
    float updateActivation(void);

    void addActivationHist(float activation);
    float getActivationHist(int time);

    void updateExecutability(void);
    float getExecutability(void);

    void setToExecute(bool execute);
    bool isSelectedToExecute();

    int getLinkCnt(LinkType type);

    void updateLinkCnt(void);

protected:

    float calcPreviousActivation();
    float calcExternActivation();
    float calcSpreadActivation();

    void clearConditions(void);
    void clearEffects(void);

    void addCondition(CEbnCondition * pCondition);
    void addPostEffect(CEbnEffect * pEffect);

    bool hasCondition(CEbnCondition * pCondition);
    bool hasEffect(CEbnEffect * pEffect);

    bool hasToLink(CEbnLink * pLink);
    bool hasFromLink(CEbnLink * pLink);

    int getPredecessorLinkToCnt(void) { return mPredecessorLinkToCnt; }
    int getSuccessorLinkToCnt(void) { return mSuccessorLinkToCnt; }
    int getConflictorLinkToCnt(void) { return mConflictorLinkToCnt; }
    int getReceptorLinkToCnt(void) { return mReceptorLinkToCnt; }
    int getGoalLinkToCnt(void) { return mGoalLinkToCnt; }
	
private:
    CEbnAction * mpAction;
    float mModuleActivation;

    float mExternActivation;
    float mSpreadActivation;
    float mPreviousActivation;

    bool mSelectedToExecute;

    float mExecutability;

    vector<CEbnCondition *> mConditions;
    vector<CEbnEffect *> mEffects;

    /* The links start from this competence module */
    vector<CEbnLink *> mFromLinks;
    /* The links point to this competence module */
    vector<CEbnLink *> mToLinks;

    vector<float> mActivationHist;

    int mPredecessorLinkToCnt;
    int mSuccessorLinkToCnt;
    int mConflictorLinkToCnt;
    int mReceptorLinkToCnt;
    int mGoalLinkToCnt;
};

#endif
